#ifndef _DETU_MEDIA_VENC_CHN_IMP_H_
#define _DETU_MEDIA_VENC_CHN_IMP_H_

#include "venc_chn.h"
#include "mutex.h"

#include "hi_common.h"
#include "hi_comm_venc.h"

namespace detu_media
{

class VencMgrImp;
typedef struct _FrameStruct
{
	FrameInfo frameInfo;
	VENC_STREAM_S stream;
	Int32_t ref;
	Int32_t streamRef;

} FrameStruct;

typedef std::map<HI_U32, FrameStruct *> FrameStructMap;

typedef std::map<HI_U32, FrameInfo *> FrameInfoMap;

class VencChnImp : public VencChn
{
protected:
    VencChnImp();

    virtual ~VencChnImp();

	friend class VencMgrImp;

public:
    virtual S_Result start(int picNum = -1);

    virtual S_Result stop(void);

    virtual bool isStarted(void);

    virtual S_Result getId(int &id);

	virtual S_Result getFd(int &fd);

	virtual S_Result getBindCfg(Json::Value& config);

	virtual S_Result getStream(Uint32_t& seq, const Uint8_t* bufAddr, const Uint32_t bufSize, StreamInfo& info, const Int32_t milliSec = -1);

	virtual S_Result getStream(Uint32_t& seq, Stream& stream, StreamInfo& info, const Int32_t milliSec = -1);

	virtual S_Result requestIDR(const bool isInstant = true);

	virtual S_Result getFrame(Uint32_t& seq, FrameInfo* &info);

	virtual S_Result releaseFrame(Uint32_t& seq);

    virtual S_Result SendFrame(DT_VIDEO_FRAME_INFO_S* VideoFrameInfo, const Int32_t milliSec = -1);

private:

	static void *getStreamTask(void *p);

	static void stopTask(void *p);

	S_Result setChnParam(void);

	S_Result setChnParam(const Json::Value& oldConfig, const Json::Value& newConfig);

    S_Result init(const Json::Value& config);

    S_Result deInit(void);

    bool isInited(void);

	S_Result initVencAttr(const Json::Value& config);

	S_Result initChnParam(const Json::Value& config);

    S_Result deInitVencAttr(void);

	S_Result initGopAttr(const Json::Value& config);

    S_Result deInitGopAttr(void);

	S_Result initRcAttr(const Json::Value& config);

    S_Result deInitRcAttr(void);

	S_Result setChnAttr(const Json::Value& oldConfig, const Json::Value& newConfig);

	S_Result setVencAttr(const Json::Value& config);

	S_Result setGopAttr(const Json::Value& config);

	S_Result setRcAttr(const Json::Value& config);

	S_Result setRcParam(void);

	static S_Result callbackAll(const void* clientData, const std::string& name, const Json::Value& oldConfig, const Json::Value& newConfig, Json::Value& response);

	S_Result callback(const void* clientData, const std::string& name, const Json::Value& oldConfig, const Json::Value& newConfig, Json::Value& response);

private:
	//VENC ATTR PARAM
	constexpr static const VENC_ATTR_H264_S defH264Attr =
	{
	};

	constexpr static const VENC_ATTR_H265_S defH265Attr =
	{
	};

	constexpr static const VENC_ATTR_JPEG_S defJpegAttr =
	{
		.bSupportDCF 			= HI_TRUE,
	};

	constexpr static const VENC_ATTR_MJPEG_S defMjpegAttr =
	{
	};

	constexpr static const VENC_ATTR_PRORES_S defProresAttr =
	{
	};

	//RC ATTR PARAM
	constexpr static const VENC_H264_CBR_S defH264Cbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32BitRate 			= 30720
	};

	constexpr static const VENC_H264_VBR_S defH264Vbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32MaxBitRate 			= 30720
	};

	constexpr static const VENC_H264_AVBR_S defH264AVbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32MaxBitRate 			= 30720
	};

	constexpr static const VENC_H264_FIXQP_S defH264FixQp =
	{
		.u32Gop 				= 50,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32IQp 				= 25,
		.u32PQp 				= 30,
		.u32BQp 				= 32
	};

	constexpr static const VENC_H264_QPMAP_S defH264QpMap =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 1,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25
	};

	constexpr static const VENC_MJPEG_CBR_S defMjpegCbr =
	{
		.u32StatTime 			= 1,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32BitRate 			= 40960
	};

	constexpr static const VENC_MJPEG_VBR_S defMjpegVbr =
	{
		.u32StatTime 			= 1,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32MaxBitRate 			= 40960
	};

	constexpr static const VENC_MJPEG_FIXQP_S defMjpegFixQp =
	{
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32Qfactor 			= 95
	};

	constexpr static const VENC_H265_CBR_S defH265Cbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32BitRate 			= 20480
	};

	constexpr static const VENC_H265_VBR_S defH265Vbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32MaxBitRate 			= 20480
	};

	constexpr static const VENC_H265_AVBR_S defH265AVbr =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 5,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32MaxBitRate 			= 20480
	};

	constexpr static const VENC_H265_FIXQP_S defH265FixQp =
	{
		.u32Gop 				= 50,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.u32IQp 				= 25,
		.u32PQp 				= 30,
		.u32BQp 				= 32
	};

	constexpr static const VENC_H265_QPMAP_S defH265QpMap =
	{
		.u32Gop 				= 50,
		.u32StatTime 			= 1,
		.u32SrcFrameRate 		= 25,
		.fr32DstFrameRate 		= 25,
		.enQpMapMode 			= VENC_RC_QPMAP_MODE_MEANQP
	};

	//GOP ATTR PARAM
	constexpr static const VENC_GOP_NORMALP_S defNormalP =
	{
		.s32IPQpDelta 			= 3
	};

	constexpr static const VENC_GOP_DUALP_S defDualP =
	{
		.u32SPInterval 			= 3,
		.s32SPQpDelta 			= 2,
		.s32IPQpDelta 			= 4
	};

	constexpr static const VENC_GOP_SMARTP_S defSmartP =
	{
		.u32BgInterval 			= 1200,
		.s32BgQpDelta 			= 7,
		.s32ViQpDelta 			= 2,
	};

	constexpr static const VENC_GOP_ADVSMARTP_S defAdvSmartP =
	{
		.u32BgInterval 			= 1200,
		.s32BgQpDelta 			= 7,
		.s32ViQpDelta 			= 2,
	};

	constexpr static const VENC_GOP_BIPREDB_S defBipredB =
	{
		.u32BFrmNum 			= 2,
		.s32BQpDelta 			= -2,
		.s32IPQpDelta 			= 3
	};

	constexpr static const VENC_CHN_ATTR_S defaultChnAttr =
	{
		.stVencAttr 			=
		{
			.enType 			= PT_H265,
			.u32MaxPicWidth 	= 3968,
			.u32MaxPicHeight 	= 2768,
			.u32BufSize 		= 14880000,
			.u32Profile 		= 0,
			.bByFrame 			= HI_FALSE,
			.u32PicWidth 		= 3968,
			.u32PicHeight 		= 2768,
			{
				.stAttrH265e 	= defH265Attr
			}
		},
		.stRcAttr 				=
		{
			.enRcMode 			= VENC_RC_MODE_H265VBR,
			{
				.stH265Vbr 		= defH265Vbr
			}
		},
		.stGopAttr 				=
		{
			.enGopMode 			= VENC_GOPMODE_NORMALP,
			{
				.stNormalP 		= defNormalP
			}
		}
	};

	constexpr static const VENC_CHN_PARAM_S defaultChnParam =
	{
		.bColor2Grey 			= HI_FALSE,
		.u32Priority			= 0,
		.u32MaxStrmCnt			= 200,
		.u32PollWakeUpFrmCnt	= 1,
		.stCropCfg 				=
		{
			.bEnable 			= HI_FALSE,
			.stRect				=
			{
				.s32X			= 0,
				.s32Y			= 0,
				.u32Width		= 0,
				.u32Height		= 0,
			}
		},
		.stFrameRate			=
		{
			.s32SrcFrmRate		= 25,
			.s32DstFrmRate		= 25,
		}
	};


public:
	bool						fStartResv;
	FrameStructMap				fFrameStructMap;
	FrameInfoMap				fFrameInfoMap;
	HI_U32						fFrameRate;
	Resolution					fResolution;

private:

	VENC_CHN			fChnId;
	VENC_CHN_ATTR_S 	fChnAttr;
	VENC_CHN_PARAM_S	fChnParam;
	EncodeType			fEncType;
	Json::Value 		fBindCfg;

	Uint32_t			fSeq;
	Uint32_t			fStreamRef;
    Uint64_t            fLastPTS;
	VENC_STREAM_S 		fStream;
	pthread_cond_t 		fCond;

	int                 fRef;
    bool                fInited;
    detu_infra::Mutex   fMutex;
	detu_infra::Mutex   fgetFrameMutex;
};

}

#endif
